package com.derschmale.wick3d.core.data
{
	import com.derschmale.wick3d.core.geometry.Triangle3D;
	import com.derschmale.wick3d.core.imagemaps.UVCoords;
	import com.derschmale.wick3d.materials.DisplayObjectMaterial;
	import com.derschmale.wick3d.materials.TextureMaterial;
	
	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	
	public class ShaderData
	{
		private var _srcBmps : Dictionary = new Dictionary();
		private var _rects : Dictionary = new Dictionary();
		private var _uvMin : Dictionary = new Dictionary();
		private var _uvMax : Dictionary = new Dictionary();
		private var _drawBmps : Dictionary = new Dictionary(); 
		private var _localRects : Dictionary = new Dictionary();
		private static const ORIGIN : Point = new Point();
		
		public function getTriangleBitmapData(triangle : Triangle3D) : BitmapData
		{
			var src : BitmapData, dst : BitmapData;
			var rect : Rectangle;
			if (!_srcBmps[triangle]) generateData(triangle);
			else if (triangle.material is DisplayObjectMaterial && DisplayObjectMaterial(triangle.material).animated) generateBitmapData(triangle);
			src = _srcBmps[triangle];
			dst = _drawBmps[triangle];
			rect = _localRects[triangle];
			dst.copyPixels(src, rect, ORIGIN);
			return dst;
		}
		
		public function getRectangle(triangle : Triangle3D) : Rectangle
		{
			if (!_rects[triangle]) generateData(triangle);
			return _rects[triangle];
		}
		
		public function getMinimumUV(triangle : Triangle3D) : UVCoords
		{
			if (!_uvMin[triangle]) generateData(triangle);
			return _uvMin[triangle];
		}
		
		public function getMaximumUV(triangle : Triangle3D) : UVCoords
		{
			if (!_uvMax[triangle]) generateData(triangle);
			return _uvMax[triangle];
		}
		
		private function generateData(triangle : Triangle3D) : void
		{
			var bmp : BitmapData = TextureMaterial(triangle.material).bitmapData;
			var w : Number = bmp.width, h : Number = bmp.height;
			var minU : Number = triangle.uv1.u, minV : Number = triangle.uv1.v;
			var maxU : Number = triangle.uv1.u, maxV : Number = triangle.uv1.v;
			var min : UVCoords, max : UVCoords;
			var rect : Rectangle;
			
			if (triangle.uv2.u < minU) minU = triangle.uv2.u;
			else if (triangle.uv2.u > maxU) maxU = triangle.uv2.u;
			
			if (triangle.uv3.u < minU) minU = triangle.uv3.u;
			else if (triangle.uv3.u > maxU) maxU = triangle.uv3.u;
			
			if (triangle.uv2.v < minV) minV = triangle.uv2.v;
			else if (triangle.uv2.v > maxV) maxV = triangle.uv2.v;
			
			if (triangle.uv3.v < minV) minV = triangle.uv3.v;
			else if (triangle.uv3.v > maxV) maxV = triangle.uv3.v;
			
			min = new UVCoords(minU, minV);
			max = new UVCoords(maxU, maxV);
			
			_uvMin[triangle] = min;
			_uvMax[triangle] = max;
			
			rect = new Rectangle(minU*w, minV*h, (maxU-minU)*w, (maxV-minV)*h);
			_rects[triangle] = rect;
			_localRects[triangle] = new Rectangle(0, 0, rect.width, rect.height);
			
			generateBitmapData(triangle);
		}
		
		private function generateBitmapData(triangle : Triangle3D) : void
		{
			var rect : Rectangle = _rects[triangle];
			var bmp : BitmapData;
			
			if (!_srcBmps[triangle]) {
				try {
					_srcBmps[triangle] = new BitmapData(rect.width, rect.height, false);
				}
				catch (error : Error) {
					_srcBmps[triangle] = new BitmapData(1, 1, false);
				}
			}
			bmp = _srcBmps[triangle];
			bmp.copyPixels(TextureMaterial(triangle.material).bitmapData, rect, ORIGIN);
			_srcBmps[triangle] = bmp;
			_drawBmps[triangle] = new BitmapData(bmp.width, bmp.height, false);
		}
	}
}